在建立使用者驗證機制時,通常我們會用 使用者名稱(Username), 電子信箱 (E-Mail) 及 密碼(Password) 來建立 User 表單。基於資安的保護,使用者在表單所填寫的密碼並不會直接儲存到資料庫內,而是先將密碼加密完成後的hash,再存到資料庫裡。
舉例來說:當使用者建立帳戶時所輸入的資訊
再來看看 log 發生了什麼事?
注意看圖片內最後一行就是把密碼加密成為 “$2a$12…zv706” 後再存入資料庫裡,這其中的魔法就是 BCrypt gem 幫我們做的好事。BCrypt 提供 rails 開發者 has_secure_password 方法來做單向隨機加密及驗證在指定的 password_digest 欄位。順便一提,當使用 has_secure_password 方法時,會自動附帶3個驗證:
貼心的 Rails 在 Gemfile 裡已有提供 BCrypt gem 來做加密和驗證功能。
設定上還蠻容易的,在 user model 裡加上 has_secure_password 以及新增一個名為 password_digest 的欄位在 users table 就可以有加密的效果了!當需要驗證密碼時提供了authenticate 的方法來做解密的動作。例如:user.authenticate('password')這邊在使用 has_secure_password 時要注意使用的Rails版本。
在 Rails 6.0 之前,has_secure_password 機制只接受一種屬性(attribute) 設定為 password_digest,因此表格的密碼欄位名稱都必須是password_digest。而在 Rails 6.0之後,has_secure_password允許可以自訂名稱的選項 ,也就是自訂欄位名稱+底線+digest (column_name_digest)。
接著我們可以來到 rails console 測試一下
從 rails console 可以看出,只有當authenticate拿到正確的密碼時,解密後才可以取得使用者 jeff 的資料了。
參考資料:
bcrypt-ruby
Authentication and Authorization à la Rails bcrypt
Rails 6 allows configurable attribute name on has_secure_password